/* Includes ------------------------------------------------------------------*/ 
#include "gt32f030_qspi.h"
#include "gt32f030_rcc.h"
/** @addtogroup GT32F030_StdPeriph_Driver
  * @{
  */
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/

/* SPI RUN mask */
#define CR0_RUN_Set             ((uint32_t)0x20000000)
#define CR0_RUN_Reset           ((uint32_t)0xDFFFFFFF)
#define CR0_HALF_DUPLEX_Set     ((uint32_t)0x10000000)
#define CR0_HALF_DUPLEX_Reset   ((uint32_t)0xEFFFFFFF)
#define CR0_LOCK_CS_Set         ((uint32_t)0x08000000)
#define CR0_LOCK_CS_Reset       ((uint32_t)0xF7FFFFFF)
#define CR0_SPI_Read_Cmd_Set    ((uint32_t)0x04000000)
#define CR0_SPI_Read_Cmd_Reset  ((uint32_t)0xFBFFFFFF)
#define CR0_SPI_QPIMode_Cmd_Set ((uint32_t)0x00800000)
#define CR0_SPI_QPIMode_Cmd_Reset ((uint32_t)0xFF7FFFFF)
#define CR1_RECV_IRQ_EN_Set     ((uint32_t)0x00040000)
#define CR1_RECV_IRQ_EN_Reset   ((uint32_t)0xFFFBFFFF)
#define CR1_RECV_TIMEOUT_IRQ_EN_Set ((uint32_t)0X00010000)
#define CR1_RECV_TIMEOUT_IRQ_EN_Reset ((uint32_t)0XFFFEFFFF)
#define CR1_DMA_EN_Set          ((uint32_t)0X00002000)
#define CR1_DMA_EN_Reset        ((uint32_t)0XFFFFDFFF)
#define STS_Busy_Set            ((uint32_t)0X00000001)
#define STS_Busy_Reset          ((uint32_t)0XFFFFFFFE)
#define 	SPI_CR_SPRMask        ((uint32_t)0x00000083)
#define 	SPI_CR_PHAMask        ((uint32_t)0x00000004)
#define 	SPI_CR_POLMask        ((uint32_t)0x00000008)
#define 	SPI_CR_MSTMask        ((uint32_t)0x00000010)
#define 	SPI_CR_SSNEN          ((uint32_t)0x00000020)
#define 	SPI_CR_SPIEN          ((uint32_t)0x00000040)

#define SPI_CR1_FIRST_BIT_CLEAR_MASK                      ((uint32_t)0x00400000)

/** @defgroup QSPI 
  * @brief QSPI driver modules
  * @{
  */ 

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/** @defgroup SPI_Private_Functions
  * @{
  */ 

/** @defgroup SPI_Init Initialization functions
 *  @brief   Initialization and functions
 *
@verbatim    
 ===============================================================================
              ##### Initialization functions #####
 ===============================================================================
@endverbatim
  * @{
  */
/**
  * @brief  Deinitializes the QSPI peripheral registers to their default reset values.
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @retval None
  */
void SPI_DeInit(QSPI_TypeDef*  QSPIx)
{
  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(QSPIx));
	
  if (QSPIx == QSPI1) {
	    /* Enable SPI1 reset state */
	RCC_PeriphResetCmd(RCC_PeriphReset_QSPI1, ENABLE);
	    /* Release SPI1 reset state */
  	RCC_PeriphResetCmd(RCC_PeriphReset_QSPI1, DISABLE);

  }else if (QSPIx == QSPI2) {
	    /* Enable SPI2 reset state */
	RCC_PeriphResetCmd(RCC_PeriphReset_QSPI2, ENABLE);
	    /* Release SPI2 reset state */
  	RCC_PeriphResetCmd(RCC_PeriphReset_QSPI2, DISABLE);

  }
}


/**
  * @brief  Initializes the QSPI peripheral according to the specified
  *         parameters in the SPI_InitStruct .
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @param  SPI_InitStruct: pointer to a SPI_InitTypeDef structure that contains
  *         the configuration information.
  * @retval None
  */
void SPI_Init(QSPI_TypeDef* QSPIx,SPI_InitTypeDef* SPI_InitStruct)
{
	uint32_t tp1,tp2;
  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(QSPIx));
	assert_param(IS_SPI_PHASE(SPI_InitStruct->SPI_Phase));
	assert_param(IS_SPI_POLE(SPI_InitStruct->SPI_Pole));
	assert_param(IS_SPI_TERMINAL(SPI_InitStruct->SPI_Terminal));

	
	tp1 =  (SPI_InitStruct->SPI_Phase<<10)       | \
	       (SPI_InitStruct->SPI_Pole<<9)        | \
		     (SPI_InitStruct->SPI_Terminal<<4);    

  tp2 =  (SPI_InitStruct->ClockDivide<<8)|\
        (SPI_InitStruct->ClockRate<<0);
	QSPIx->CR1 = tp1;
  QSPIx->TIM = tp2;

}
/**
  * @brief  Fills each SPI_InitStruct member with its default value.
  * @param  SPI_InitStruct : pointer to a SPI_InitTypeDef structure which will be initialized.
  * @retval None
  */
  void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct)
  {
  /*--------------- Reset QSPI init structure parameters values -----------------*/

	/* initialize the SPI_Mode member */
	SPI_InitStruct->SPI_Terminal = SPI_Terminal_Master;
	/* Initialize the SPI_Pole member */
	SPI_InitStruct->SPI_Pole = SPI_Pole_Low;
	/* Initialize the SPI_Phase member */
	SPI_InitStruct->SPI_Phase = SPI_Phase_First;

	/* Initialize the ClockDivide member */
	SPI_InitStruct->ClockDivide = 0x04;
	/* Initialize the ClockRate member */
	SPI_InitStruct->ClockRate = 0x02;

  }
  
/**
  * @brief  Enables or disables the specified SPI peripheral.
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @param  NewState: new state of the QSPIx peripheral. 
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
  void SPI_RunCmd(QSPI_TypeDef* QSPIx, FunctionalState NewState)
  {
	/* Check the parameters */
	assert_param(IS_SPI_ALL_PERIPH(QSPIx));
	assert_param(IS_FUNCTIONAL_STATE(NewState));
	if (NewState != DISABLE)
	{
	  /* Enable the selected SPI peripheral */
	  QSPIx->CR0 |= CR0_RUN_Set;
	}
	else
	{
	  /* Disable the selected SPI peripheral */
	  QSPIx->CR0 &= CR0_RUN_Reset;
	}
  }

/**
  * @brief  Enables or disables the half duplex SPI mode.
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @param  NewState: new state of the QSPIx peripheral. 
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
  void SPI_Halfduplex_Cmd(QSPI_TypeDef* QSPIx, FunctionalState NewState)
  {
	/* Check the parameters */
	assert_param(IS_SPI_ALL_PERIPH(QSPIx));
	assert_param(IS_FUNCTIONAL_STATE(NewState));
	if (NewState != DISABLE)
	{
	  /* Enable the Half duplex SPI mode */
	  QSPIx->CR0 |= CR0_HALF_DUPLEX_Set;
	}
	else
	{
	  /* Disable the half duplex SPI mode and enable the full duplex SPI mode */
	  QSPIx->CR0 &= CR0_HALF_DUPLEX_Reset;
	}
  }
  /**
  * @brief  Enables or disables the half duplex SPI mode.
   * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @param  NewState: new state of the QSPIx peripheral. 
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
  void SPI_Lock_CS_Cmd(QSPI_TypeDef* QSPIx, FunctionalState NewState)
  {
	/* Check the parameters */
	assert_param(IS_SPI_ALL_PERIPH(QSPIx));
	assert_param(IS_FUNCTIONAL_STATE(NewState));
	if (NewState != DISABLE)
	{
	  /* keep the SSn pin in the same state as the previous frame */
	  QSPIx->CR0 |= CR0_LOCK_CS_Set;
	}
	else
	{
	  /* Cansel_SSn: cancel the SSn pin in the same state as the previous frame */
	  QSPIx->CR0 &= CR0_LOCK_CS_Reset;
	}
  }
  /**
  * @brief  Enables or disables the half duplex SPI mode.
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @param  NewState: new state of the QSPIx peripheral. 
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
  void SPI_Read_Cmd(QSPI_TypeDef* QSPIx, FunctionalState NewState)
  {
	/* Check the parameters */
	assert_param(IS_SPI_ALL_PERIPH(QSPIx));
	assert_param(IS_FUNCTIONAL_STATE(NewState));
	if (NewState != DISABLE && QSPIx->CR0 & CR0_HALF_DUPLEX_Set)
	{
	  /* When half-duplex position 1, that position 1 selects SPI read */
	  QSPIx->CR0 |= CR0_SPI_Read_Cmd_Set;
	}
	else
	{
	  /* When half-duplex position 1, that position 0 selects SPI write */
	  QSPIx->CR0 &= CR0_SPI_Read_Cmd_Reset;
	}
  }

    /**
  * @brief  Enables or disables the QPI mode.
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @param  NewState: new state of the QSPIx peripheral. 
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
  void SPI_QPIMode_Cmd(QSPI_TypeDef* QSPIx, FunctionalState NewState)
  {
	/* Check the parameters */
	assert_param(IS_SPI_ALL_PERIPH(QSPIx));
	assert_param(IS_FUNCTIONAL_STATE(NewState));
	if (NewState != DISABLE && QSPIx->CR0 & CR0_HALF_DUPLEX_Set)
	{
	  /* Enables  the QPI mode. */
	  QSPIx->CR1 |= CR0_SPI_QPIMode_Cmd_Set;
	}
	else
	{
	  /* Disable the QPI mode. */
	  QSPIx->CR1 &= CR0_SPI_QPIMode_Cmd_Reset;
	}
  }
  /**
  * @brief  Enables or disables timeout interrupts for SPIx.
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @param  NewState: new state of the SPIx timeout interrupts . 
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
  void SPI_RECV_IRQ_Cmd(QSPI_TypeDef* QSPIx, FunctionalState NewState)
  {
	/* Check the parameters */
	assert_param(IS_SPI_ALL_PERIPH(QSPIx));
	assert_param(IS_FUNCTIONAL_STATE(NewState));
	if (NewState != DISABLE)
	{
	  /* Enable the selected SPI peripheral */
	  QSPIx->CR1 |= CR1_RECV_IRQ_EN_Set;
	}
	else
	{
	  /* Disable the selected SPI peripheral */
	  QSPIx->CR1 &= CR1_RECV_IRQ_EN_Reset;
	}

  }
/**
  * @brief  Enables or disables receiving interrupts for SPIx.
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @param  NewState: new state of the SPIx receiving interrupts . 
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
  void SPI_RECV_TIMEOUT_IRQ_Cmd(QSPI_TypeDef* QSPIx, FunctionalState NewState)
  {
	/* Check the parameters */
	assert_param(IS_SPI_ALL_PERIPH(QSPIx));
	assert_param(IS_FUNCTIONAL_STATE(NewState));
	if (NewState != DISABLE)
	{
	  /* Enable the selected SPI peripheral */
	  QSPIx->CR1 |= CR1_RECV_TIMEOUT_IRQ_EN_Set;
	}
	else
	{
	  /* Disable the selected SPI peripheral */
	  QSPIx->CR1 &= CR1_RECV_TIMEOUT_IRQ_EN_Reset;
	}

  }

/**
  * @brief  Checks whether the specified SPI/I2S interrupt has occurred or not.
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @param  SPI_IT: specifies the SPI/I2S interrupt source to check. 
  *   This parameter can be one of the following values:
  *     @arg SPI_IT_RECV: The data in RxFIFO is greater than or equal to half.
  *     @arg SPI_IT_RECV_TIMEOUT:  When RxFIFO is not empty, no data is read within 128 HCLK cycles.
  * @retval The new state of SPI_IT (SET or RESET).
  */
  ITStatus  SPI_GetITStatus(QSPI_TypeDef* QSPIx, uint32_t SPI_IT){
  FlagStatus bitstatus = RESET;
	/* Check the parameters */
	assert_param(IS_SPI_ALL_PERIPH(QSPIx));
	assert_param(IS_SPI_GET_IT(SPI_IT));
  

  
	/* Check the status of the specified SPI interrupt */
	if ((QSPIx->CR1 & SPI_IT) != (uint32_t)RESET )
	{
	  /* SPI_IT is set */
	  bitstatus = SET;
	}
	else
	{
	  /* SPI_IT is reset */
	  bitstatus = RESET;
	}
	/* Return the SPI_IT status */
	return bitstatus;

  }
  /**
  * @brief  Checks whether the specified SPI/I2S interrupt has occurred or not.
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @retval The new state of SPI_BUSY (SET or RESET).
  */
  FlagStatus  SPI_GetBusyStatus(QSPI_TypeDef* QSPIx){
    FlagStatus bitstatus = RESET;
    /* Check the parameters */
    assert_param(IS_SPI_ALL_PERIPH(QSPIx));

    /* Check the status of the specified SPI interrupt */
    if ((QSPIx->STS & STS_Busy_Set) != (uint32_t)RESET )
    {
      /* SPI_IT is set */
      bitstatus = SET;
    }
    else
    {
      /* SPI_IT is reset */
      bitstatus = RESET;
    }
    /* Return the SPI_IT status */
    return bitstatus;
  
    }
/**
  * @brief  Clears the SPIx Interrupt flag.
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @param  SPI_FLAG: specifies the SPI_IT flag to clear. 
  *   @arg SPI_IT_RECV_CLR: The data in RxFIFO is greater than or equal to half.
  *   @arg SPI_IT_RECV_TIMEOUT_CLR:  When RxFIFO is not empty, no data is read within 128 HCLK cycles.
  * @retval None
  */
  void SPI_ClearFlag(QSPI_TypeDef* QSPIx, uint32_t SPI_FLAG){

  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(QSPIx));
  assert_param(IS_SPI_CLR_IT(SPI_FLAG));
    
    /* Clear the selected SPI Interrupt flag */
    QSPIx->CR1 |= (uint32_t)SPI_FLAG;



  }
/**
  * @brief  Select SPI as which mode.
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @param  SPIMode_TypeDef:  Select SPI as which mode. 
  *   @arg SPI_Mode: Select SPI as SPI mode.
  *   @arg SPI_Dual_Mode: Select SPI as SPI Dual mode.
  *   @arg SPI_Quad_Mode:  Select SPI as SPI Quad mode .
  * @retval None
  */
  void SPI_Mode_Sel(QSPI_TypeDef* QSPIx, SPIMode_TypeDef Mode){

  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(QSPIx));
  assert_param(IS_SPI_MODE(Mode));
    
    /* Select SPI as which mode. */
    QSPIx->CR1 &= ~((uint32_t)0x07);
    QSPIx->CR1 |= (uint32_t)Mode;



  }


/**
  * @brief  Configures the data size for the selected SPI.
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @param  SPI_DataSize: specifies the SPI data size.
  *   This parameter can be one of the following values:
  *     @arg SPI_DataSize_32b: Set data frame format to 32bit
  *     @arg SPI_DataSize_24b: Set data frame format to 24bit
  *     @arg SPI_DataSize_16b: Set data frame format to 16bit
  *     @arg SPI_DataSize_8b: Set data frame format to 8bit
  *     @arg SPI_DataSize_4b: Set data frame format to 4bit
  * @retval None
  */
void SPI_DataSizeConfig(QSPI_TypeDef* QSPIx, uint8_t SPI_DataSize)
{
  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(QSPIx));
  assert_param(IS_SPI_DATASIZE(SPI_DataSize));
  /* Clear WORD_LENGTH bit */
  QSPIx->CR1 &= (uint32_t)~SPI_DataSize_32b;
  /* Set new WORD_LENGTH bit value */
  QSPIx->CR1 |= SPI_DataSize;
}



/**
  * @brief  Enables or disables the SPIx DMA interface.
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @param  NewState: new state of the selected SPI DMA transfer request.
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
  void SPI_DMACmd(QSPI_TypeDef* QSPIx, FunctionalState NewState)
  {
	/* Check the parameters */
	assert_param(IS_SPI_ALL_PERIPH(QSPIx));
	assert_param(IS_FUNCTIONAL_STATE(NewState));
	if (NewState != DISABLE)
	{
	  /* Enable the selected SPI DMA requests */
	  QSPIx->CR1 |= CR1_DMA_EN_Set;
	}
	else
	{
	  /* Disable the selected SPI DMA requests */
	  QSPIx->CR1 &= CR1_DMA_EN_Reset;
	}
  }
/**
  * @brief  Transmits a Data through the SPIx peripheral.
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @param  Data : Data to be transmitted.
  * @retval None
  */
  void SPI_SendData(QSPI_TypeDef* QSPIx, uint32_t Data){

  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(QSPIx));
  
  /* Write in the DR register the data to be sent */
  QSPIx->DATA = Data;


  }
/**
  * @brief  Transmits a Data through the SPIx peripheral.
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @param  Command : Command to be transmitted.
  * @retval None
  */
  void SPI_SendCommand(QSPI_TypeDef* QSPIx, uint8_t Command){

	/* Check the parameters */
	assert_param(IS_SPI_ALL_PERIPH(QSPIx));
	
	/* Write in the CMD register the data to be sent */
	QSPIx->CMD = Command;
  
  
	}
  /**
  * @brief  Returns the most recent received data by the SPIx peripheral. 
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @retval The value of the received data.
  */
  uint32_t SPI_ReceiveData(QSPI_TypeDef* QSPIx){
  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(QSPIx));
  
  /* Return the data in the DATA register */
  return QSPIx->DATA;



  }

/**
  * @brief  The number of bytes transmitted by SPIx.
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @param  Command : The number of bytes transmitted by SPIx.
  * @retval None
  */
  void SPI_TransmitLength(QSPI_TypeDef* QSPIx, uint32_t length){

    /* Check the parameters */
    assert_param(IS_SPI_ALL_PERIPH(QSPIx));
    
    /* The number of bytes transmitted by SPI */
    QSPIx->XFER = length;
    
    
    }


/**
  * @brief  Configures the first bit for the selected SPI.
  * @param  SPIx: Select the SPI or the SPI peripheral. 
  *         This parameter can be one of the following values:
  *         SPI1, SPI2.
  * @param  FirstBit: specifies the SPI first bit.
  *   @arg  SPI_FirstBit_MSB: Set the first bit to MSB.
  *   @arg  SPI_FirstBit_LSB: Set the first bit to LSB.
  * @retval None
  */
void SPI_FirstBitConfig(QSPI_TypeDef* SPIx, SPIFirstBit_TypeDef FirstBit) {
  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(SPIx));
  assert_param(IS_SPI_FIRSTBIT(FirstBit));

  /* Clear the FIRST_BIT bit */
  SPIx->CR1 &= ~SPI_CR1_FIRST_BIT_CLEAR_MASK;
  /* Set the FIRST_BIT bit */
  SPIx->CR1 |= FirstBit << 22;
}

/**
  * @brief  Returns the most recent received data by the SPIx peripheral. 
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @retval The value of the received data.
  */
uint32_t SPI_ReceiveData32(QSPI_TypeDef* SPIx) {
  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(SPIx));

  /* Return the data in the DATA register */
  if (SPIx == QSPI1) {
    return QSPI1_DATA;
  } else {
    return QSPI2_DATA;
  }
}

/**
  * @brief  Returns the current Receive QSPI FIFO filled level.
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @retval Number of valid bytes which are being held in the FIFO.
  */
uint32_t SPI_GetReceiveFIFOLevel(QSPI_TypeDef* SPIx) {
  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(SPIx));

  uint32_t tmpreg = SPIx->STS;
  if (tmpreg & 0x0f000000) {
    return (tmpreg >> 24) & 0xf;
  } else {
    if ((tmpreg & 0x0100) != RESET) {
      return 0;
    } else {
      return 0xf;
    }
  }
}

/**
  * @brief  Returns the current Transmit QSPI FIFO filled level.
  * @param  QSPIx: Select the QSPI or the QSPI peripheral. 
  *         This parameter can be one of the following values:
  *         QSPI1, QSPI2.
  * @retval Number of valid bytes which are being held in the FIFO.
  */
uint32_t SPI_GetTransmitFIFOLevel(QSPI_TypeDef* SPIx) {
  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(SPIx));

  uint32_t tmpreg = SPIx->STS;
  if (tmpreg & 0x00f00000) {
    return (tmpreg >> 20) & 0xf;
  } else {
    if ((tmpreg & 0x0020) != RESET) {
      return 0;
    } else {
      return 0xf;
    }
  }
}

/**
  * @}  
  */ 





  
/**
  * @}  
  */

/**
  * @}  
  */ 

/**
  * @}
  */ 
/************************ (C) COPYRIGHT Giantec Semicondutor Inc *****END OF FILE****/
